package gamelogic

import (
	"encoding/json"
	"fmt"
	"os/exec"
	"reflect"
	"server_cluster/common/mysock"
	"strconv"
	"strings"
	"unsafe"

	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/protoc/pb"
	"server_cluster/logic/db"
	"server_cluster/logic/game_config"
	"server_cluster/logic/sharemem"
)

/**************************************** GM功能函数 ****************************************/

// GMAddItem 添加道具
func (g *GMCmd) GMAddItem(itemId int32, itemCount int32) bool {
	ret := AddItems(map[int32]int32{itemId: itemCount}, g.User)
	if ret != config.OK {
		logger.Error("add item error, ret: %v, uid: %v", ret, g.User.GetUid())
		return false
	}
	return true
}

// GMCostItem 消耗道具
func (g *GMCmd) GMCostItem(itemId int32, itemCount int32) bool {
	CostItems(map[int32]int32{itemId: itemCount}, g.User)
	return true
}

// GMAddAllItem 添加全部道具
func (g *GMCmd) GMAddAllItem(count int32) bool {
	itemMap := make(map[int32]int32)
	for _, itemConfig := range gdconf.GetItemConfigMap() {
		if itemConfig.AutoUse {
			continue
		}
		if itemConfig.Type == gdconf.ITEM_TYPE_EQUIP || itemConfig.Type == gdconf.ITEM_TYPE_EQUIP_JEWEL || itemConfig.Type == gdconf.ITEM_TYPE_WEAPON {
			continue
		}
		if itemConfig.ClientNumLimit == 1 {
			continue
		}
		itemMap[itemConfig.ItemId] = count
	}
	g.User.FreeNet = true
	ret := AddItems(itemMap, g.User)
	g.User.FreeNet = false
	if ret != config.OK {
		logger.Error("add item error, ret: %v, uid: %v", ret, g.User.GetUid())
		return false
	}
	g.GMKickPlayer()
	return true
}

// GMDelItem 删除道具
func (g *GMCmd) GMDelItem(itemId int32) bool {
	normalItem := make([]*pb.Item_Base, 0)
	for i := 0; i < len(g.User.Item.Normal); i++ {
		item := &(g.User.Item.Normal[i])
		if item.GetId() == itemId {
			normalItem = append(normalItem, &pb.Item_Base{
				Cell: int32(i),
				Id:   item.GetId(),
				Type: int32(item.Type),
				Num:  0,
			})
			if item.Id.OldVal != 0 {
				item.Clear()
			} else {
				item.MemInit()
			}
			break
		}
	}
	specialItem := make([]*pb.Item_Base, 0)
	for i := 0; i < len(g.User.Item.Special); i++ {
		item := &(g.User.Item.Special[i])
		if item.GetId() == itemId {
			specialItem = append(specialItem, &pb.Item_Base{
				Cell: int32(i),
				Id:   item.GetId(),
				Type: int32(item.Type),
				Num:  0,
			})
			if item.Id.OldVal != 0 {
				item.Clear()
			} else {
				item.MemInit()
			}
			break
		}
	}
	SendMsg(config.SC_ItemChangeNtf, &pb.SC_ItemChangeNtf{Item: &pb.User_Item{Normal: normalItem, Special: specialItem}}, nil, g.User)
	return true
}

// GMClearItem 清除全部道具
func (g *GMCmd) GMClearItem() bool {
	for i := 0; i < len(g.User.Item.Normal); i++ {
		item := &(g.User.Item.Normal[i])
		if item.Id.NewVal == 0 {
			continue
		}
		if item.Id.OldVal != 0 {
			item.Clear()
		} else {
			item.MemInit()
		}
	}
	for i := 0; i < len(g.User.Item.Special); i++ {
		item := &(g.User.Item.Special[i])
		if item.Id.NewVal == 0 {
			continue
		}
		if item.Id.OldVal != 0 {
			item.Clear()
		} else {
			item.MemInit()
		}
	}
	g.User.ResetItemMap()
	g.GMKickPlayer()
	return true
}

// GMAddRole 添加角色
func (g *GMCmd) GMAddRole(roleId int32) bool {
	AddUserRole(roleId, g.User)
	return true
}

// GMAddAllRole 添加所有角色
func (g *GMCmd) GMAddAllRole() bool {
	for id := range gdconf.GetRoleConfigMap() {
		AddUserRole(id, g.User)
	}
	return true
}

// GMSetRoleLevel 设置角色等级
func (g *GMCmd) GMSetRoleLevel(roleId int32, level int16) bool {
	role := g.User.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, g.User.GetUid())
		return false
	}
	role.Level = level
	roleConfig := gdconf.GetRoleConfig(roleId)
	if roleConfig == nil {
		return false
	}
	for promote := 1; promote < 100; promote++ {
		rolePromoteConfig := gdconf.GetRolePromoteConfigByGroupAndPromote(roleConfig.PromoteGroup, int32(promote))
		if rolePromoteConfig == nil {
			return false
		}
		if role.Level <= int16(rolePromoteConfig.LevelLimit) {
			role.Promote = int8(rolePromoteConfig.Promote)
			role.SetSync()
			SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: g.User.PacketUserRole(role)}, nil, g.User)
			return false
		}
	}
	return true
}

// GMSetRolePromote 设置角色突破等阶
func (g *GMCmd) GMSetRolePromote(roleId int32, promote int8) bool {
	role := g.User.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, g.User.GetUid())
		return false
	}
	role.Promote = promote
	roleConfig := gdconf.GetRoleConfig(roleId)
	if roleConfig == nil {
		return false
	}
	rolePromoteConfig := gdconf.GetRolePromoteConfigByGroupAndPromote(roleConfig.PromoteGroup, int32(promote))
	if rolePromoteConfig == nil {
		return false
	}
	role.Level = int16(rolePromoteConfig.LevelLimit)
	role.SetSync()
	SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: g.User.PacketUserRole(role)}, nil, g.User)
	return true
}

// GMSetRoleStar 设置角色星级
func (g *GMCmd) GMSetRoleStar(roleId int32, star int8) bool {
	role := g.User.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, g.User.GetUid())
		return false
	}
	role.Star = star
	role.SetSync()
	SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: g.User.PacketUserRole(role)}, nil, g.User)
	return true
}

// GMUnlockRoleTalent 解锁角色天赋
func (g *GMCmd) GMUnlockRoleTalent(roleId int32, talentId int32) bool {
	role := g.User.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, g.User.GetUid())
		return false
	}
	RoleUnlockTalent(roleId, talentId, true, g.User)
	role.SetSync()
	return true
}

// GMResetRoleTalent 重置角色天赋
func (g *GMCmd) GMResetRoleTalent(roleId int32) bool {
	role := g.User.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, g.User.GetUid())
		return false
	}
	roleConfig := gdconf.GetRoleConfig(roleId)
	if roleConfig == nil {
		return false
	}
	for i := 0; i < len(role.TalentList); i++ {
		role.TalentList[i].TalentId = 0
		role.TalentList[i].Level = 0
	}
	for _, roleTalentConfig := range gdconf.GetRoleTalentConfigMap() {
		if roleTalentConfig.TalentGroup != roleConfig.TalentGroup {
			continue
		}
		if roleTalentConfig.DefaultUnlock {
			RoleUnlockTalent(roleId, roleTalentConfig.TalentId, true, g.User)
		}
	}
	role.SetSync()
	return true
}

// GMSetRoleTalentLevel 设置角色天赋等级
func (g *GMCmd) GMSetRoleTalentLevel(roleId int32, talentId int32, level int8) bool {
	role := g.User.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, g.User.GetUid())
		return false
	}
	talent := role.GetTalent(talentId)
	if talent == nil {
		logger.Error("get talent is nil, talentId: %v, uid: %v", talentId, g.User.GetUid())
		return false
	}
	talent.Level = level
	role.SetSync()
	return true
}

// GMSetEquipLevel 设置装备等级
func (g *GMCmd) GMSetEquipLevel(equipKey int32, level int16) bool {
	equip := g.User.GetEquip4Key(equipKey)
	if equip == nil {
		logger.Error("equip not exist, equipKey: %v, uid: %v", equipKey, g.User.GetUid())
		return false
	}
	equip.Level = level
	equip.SetSync()
	SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: sharemem.PacketEquip(equip, g.User)}, nil, g.User)
	return true
}

// // GMAppendEquipAffix 追加装备词条
// func (g *GMCmd) GMAppendEquipAffix(equipKey int32) bool {
// 	equip, _ := g.User.EquipMap.Get(equipKey)
// 	if equip == nil {
// 		logger.Error("equip not exist, equipKey: %v, uid: %v", equipKey, g.User.GetUid())
// 		return false
// 	}
// 	equipConfig := sharemem.GetConfigEquip(equip.Id.NewVal)
// 	if equipConfig == nil {
// 		logger.Error("get equipConfig is nil, equipId: %v, uid: %v", equip.Id.NewVal, g.User.GetUid())
// 		return false
// 	}
// 	g.User.EquipAffixAppend(&(equip.AffixList), equipConfig, nil,g.User)
// 	equip.SetSync()
// 	SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: g.User.PacketEquip(equip)})
// 	return true
// }

// GMClearPlayer 清除玩家数据
func (g *GMCmd) GMClearPlayer() bool {
	g.User.Kick = true
	g.User.Clear = true
	return true
}

// GMKickPlayer 强制下线玩家
func (g *GMCmd) GMKickPlayer() bool {
	g.User.Kick = true
	return true
}

// GMSetTeamRole 设置队伍角色
func (g *GMCmd) GMSetTeamRole(teamId int32, roleIdList string) bool {
	split := strings.Split(roleIdList, "#")
	if len(split) != 6 {
		logger.Error("roleIdList is invalid, roleIdList: %v", roleIdList)
		return false
	}
	roles := make([]int32, 0)
	for i := 0; i < 6; i++ {
		roleId, err := strconv.Atoi(split[i])
		if err != nil {
			logger.Error("roleIdList is invalid, roleIdList: %v", roleIdList)
			return false
		}
		roles = append(roles, int32(roleId))
	}
	team := g.User.GetTeam(teamId)
	if team == nil {
		logger.Error("get team is nil, teamId: %v, uid: %v", teamId, g.User.GetUid())
		return false
	}
	team.SetFightRoleList(roles[0:4])
	team.SetAssistRoleList(roles[4:6])
	team.SetSync()
	SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OK, Team: g.User.PacketPbTeamData()}, nil, g.User)
	return true
}

// GMSetTeamName 设置队伍名称
func (g *GMCmd) GMSetTeamName(teamId int32, name string) bool {
	team := g.User.GetTeam(teamId)
	if team == nil {
		logger.Error("get team is nil, teamId: %v, uid: %v", teamId, g.User.GetUid())
		return false
	}
	team.SetName(name)
	team.SetSync()
	SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OK, Team: g.User.PacketPbTeamData()}, nil, g.User)
	return true
}

// GMSetActiveTeamId 设置当前活跃队伍id
func (g *GMCmd) GMSetActiveTeamId(teamId int32) bool {
	g.User.SetActiveTeamId(teamId)
	SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OK, Team: g.User.PacketPbTeamData()}, nil, g.User)
	return true
}

// GMSetPlayerLevel 设置玩家等级
func (g *GMCmd) GMSetPlayerLevel(level int16) bool {
	g.User.Level = level
	g.User.SetSync()
	SendMsg(config.SC_ResChangeNtf, &pb.SC_ResChangeNtf{Info: g.User.PacketUserInfo()}, nil, g.User)
	return true
}

// GMUnlockScene 解锁场景
func (g *GMCmd) GMUnlockScene(sceneId int32) bool {
	AddUserScene(sceneId, g.User)
	return true
}

// GMUnlockAllScene 解锁全部场景
func (g *GMCmd) GMUnlockAllScene() bool {
	for sceneId := range gdconf.GetSceneConfigMap() {
		AddUserScene(sceneId, g.User)
	}
	return true
}

// GMForceFinishParentQuest 强制完成父任务
func (g *GMCmd) GMForceFinishParentQuest(parentQuestId int32) bool {
	parentQuest := g.User.GetParentQuest(parentQuestId)
	if parentQuest == nil {
		logger.Error("get parentQuest is nil, parentQuestId: %v, uid: %v", parentQuestId, g.User.GetUid())
		return false
	}
	parentQuest.State = config.QUEST_STATE_FIN
	questList := parentQuest.GetQuestList()
	for _, quest := range questList {
		g.GMForceFinishQuest(parentQuestId, quest.QuestId)
	}
	parentQuest.CurrQuestId = questList[len(questList)-1].QuestId
	parentQuestConfig := gdconf.GetConfigParentQuest(parentQuest.ParentQuestId)
	if parentQuestConfig == nil {
		logger.Error("get parentQuestConfig is nil, parentQuestId: %v", parentQuest.ParentQuestId)
		return false
	}
	SendMsg(config.SC_ParentQuestUpdateNtf, &pb.SC_ParentQuestUpdateNtf{
		QuestType:   parentQuestConfig.Type,
		ParentQuest: g.User.PacketParentQuest(parentQuest),
	}, nil, g.User)
	return true
}

// GMForceFinishQuest 强制完成子任务
func (g *GMCmd) GMForceFinishQuest(parentQuestId int32, questId int32) bool {
	quest := g.User.GetQuest(parentQuestId, questId)
	if quest == nil {
		logger.Error("get quest is nil, parentQuestId: %v, questId: %v, uid: %v", parentQuestId, questId, g.User.GetUid())
		return false
	}
	questConfig := gdconf.GetConfigQuest(questId)
	if questConfig == nil {
		logger.Error("get questConfig is nil, questId: %v", questId)
		return false
	}
	quest.State = config.QUEST_STATE_FIN
	for index, questCond := range quest.GetCondList() {
		condConfig := questConfig.CondList[index]
		for paramIdx, param := range condConfig[1:] {
			questCond.ParamList[paramIdx] = param
		}
	}
	parentQuestConfig := gdconf.GetConfigParentQuest(parentQuestId)
	if parentQuestConfig == nil {
		logger.Error("get parentQuestConfig is nil, parentQuestId: %v", parentQuestId)
		return false
	}
	SendMsg(config.SC_QuestUpdateNtf, &pb.SC_QuestUpdateNtf{
		QuestType:     parentQuestConfig.Type,
		ParentQuestId: parentQuestId,
		Quest:         g.User.PacketQuest(quest),
	}, nil, g.User)
	return true
}

// GMFinishQuest 完成子任务
func (g *GMCmd) GMFinishQuest(questId int32) bool {
	questConfig := gdconf.GetConfigQuest(questId)
	if questConfig == nil {
		logger.Error("get questConfig is nil, questId: %v", questId)
		return false
	}
	for _, cond := range questConfig.CondList {
		ret := TriggerQuest(g.User, cond[0], true, cond[1:]...)
		if ret != config.OK {
			logger.Error("trigger quest error, ret: %v, uid: %v", ret, g.User.GetUid())
			return false
		}
	}
	return true
}

// GMResetParentQuest 重置父任务
func (g *GMCmd) GMResetParentQuest(parentQuestId int32) bool {
	parentQuest := g.User.GetParentQuest(parentQuestId)
	if parentQuest != nil {
		parentQuest.MemInit()
	}
	g.User.AddParentQuest(parentQuestId)
	g.GMKickPlayer()
	return true
}

//// GMResetQuest 重置子任务
//func (g *GMCmd) GMResetQuest(parentQuestId int32, questId int32) bool {
//	parentQuest := g.User.GetParentQuest(parentQuestId)
//	if parentQuest != nil {
//		parentQuest.MemInit()
//	}
//	g.User.AddParentQuest(parentQuestId)
//	parentQuest = g.User.GetParentQuest(parentQuestId)
//	if parentQuest == nil {
//		logger.Error("get parentQuest is nil, parentQuestId: %v, uid: %v", parentQuestId, g.User.GetUid())
//		return false
//	}
//	questList := parentQuest.GetQuestList()
//	for _, quest := range questList {
//		if quest.QuestId == questId {
//			break
//		}
//		g.GMForceFinishQuest(parentQuestId, quest.QuestId)
//	}
//	parentQuest.CurrQuestId = questId
//	parentQuestConfig := gdconf.GetConfigParentQuest(parentQuest.ParentQuestId)
//	if parentQuestConfig == nil {
//		logger.Error("get parentQuestConfig is nil, parentQuestId: %v", parentQuest.ParentQuestId)
//		return false
//	}
//	g.GMKickPlayer()
//	return true
//}

func (g *GMCmd) GMResetQuest(parentQuestId, questId int32) bool {
	questConfig := gdconf.GetConfigQuest(questId)
	if questConfig == nil {
		logger.Error("get questConfig is nil, questId: %v", questId)
		return false
	}
	parentQuestConfig := gdconf.GetConfigParentQuest(parentQuestId)
	if parentQuestConfig == nil {
		logger.Error("get parentQuestConfig is nil, parentQuestId: %v", parentQuestId)
		return false
	}
	g.User.UserQuest.MemInit()
	g.User.CleanParentQuestFinish()
	for _, data := range gdconf.GetConfigParentQuestMap() {
		if data.Id >= parentQuestId {
			continue
		}
		if data.Type != config.QUEST_TYPE_MAIN {
			continue
		}
		logger.Warn("[GMResetQuest] quest Id :%v", data.Id)
		g.User.OnParentQuestFinish(data.Id)
	}

	g.User.AddParentQuest(parentQuestConfig.Id)
	parentQuest := g.User.GetParentQuest(parentQuestConfig.Id)
	questList := parentQuest.GetQuestList()
	for _, quest := range questList {
		if quest.QuestId == questId {
			break
		}
		quest.State = config.QUEST_STATE_FIN
	}
	parentQuest.CurrQuestId = questId
	g.GMKickPlayer()
	return true
}

// GMAcceptQuest 自动接取任务
func (g *GMCmd) GMAcceptQuest() bool {
	ret := AcceptQuest(g.User)
	if ret != config.OK {
		logger.Error("accept quest error, ret: %v, uid: %v", ret, g.User.GetUid())
		return false
	}
	return true
}

// GMTriggerQuest 触发任务
func (g *GMCmd) GMTriggerQuest(cond int32, paramList string) bool {
	param := make([]int32, 0)
	if paramList != "" {
		for _, s := range strings.Split(paramList, "#") {
			p, err := strconv.Atoi(s)
			if err != nil {
				logger.Error("param format error, paramList: %v, uid: %v", paramList, g.User.GetUid())
				return false
			}
			param = append(param, int32(p))
		}
	}
	ret := TriggerQuest(g.User, cond, true, param...)
	if ret != config.OK {
		logger.Error("trigger quest error, ret: %v, uid: %v", ret, g.User.GetUid())
		return false
	}
	return true
}

// GMUnlockDailyQuest 解锁每日任务
func (g *GMCmd) GMUnlockDailyQuest() bool {
	g.User.UserQuest.DailyQuestUnlock = true
	RefreshDailyQuest(g.User)
	return true
}

// GMClearQuest 清除全部任务
func (g *GMCmd) GMClearQuest() bool {
	g.User.UserQuest.MemInit()
	g.GMKickPlayer()
	return true
}

// GMExecEvent 执行事件
func (g *GMCmd) GMExecEvent(_type int32, paramList string) bool {
	param := make([]int32, 0)
	if paramList != "" {
		for _, s := range strings.Split(paramList, "#") {
			p, err := strconv.Atoi(s)
			if err != nil {
				logger.Error("param format error, paramList: %v, uid: %v", paramList, g.User.GetUid())
				return false
			}
			param = append(param, int32(p))
		}
	}
	ret := ExecEvent(g.User, _type, param...)
	if ret != config.OK {
		logger.Error("exec event error, ret: %v, uid: %v", ret, g.User.GetUid())
		return false
	}
	return true
}

// GMDumpQuest 转储任务数据
func (g *GMCmd) GMDumpQuest() string {
	dumpQuestList := func(questList []*sharemem.Quest) string {
		questListData := ""
		questListData += "["
		for index, quest := range questList {
			data, _ := json.Marshal(g.User.PacketQuest(quest))
			questListData += string(data)
			if index != len(questList)-1 {
				questListData += ","
			}
		}
		questListData += "]"
		return questListData
	}
	data := ""
	data += fmt.Sprintf("============================== GMDumpQuest uid: %v ==============================\n", g.User.GetUid())
	for _, parentQuest := range g.User.GetParentQuestAll() {
		switch parentQuest.Type {
		case config.QUEST_TYPE_MAIN:
			data += fmt.Sprintf("[MainQuest] ParentQuestId: %v, State: %v, QuestList: %v, CurrQuestId: %v\n",
				parentQuest.ParentQuestId, parentQuest.State, dumpQuestList(parentQuest.GetQuestList()), parentQuest.CurrQuestId)
		case config.QUEST_TYPE_SIDE:
			data += fmt.Sprintf("[SideQuest] ParentQuestId: %v, State: %v, QuestList: %v, CurrQuestId: %v\n",
				parentQuest.ParentQuestId, parentQuest.State, dumpQuestList(parentQuest.GetQuestList()), parentQuest.CurrQuestId)
		case config.QUEST_TYPE_DAILY:
			data += fmt.Sprintf("[DailyQuest] ParentQuestId: %v, State: %v, QuestList: %v, CurrQuestId: %v\n",
				parentQuest.ParentQuestId, parentQuest.State, dumpQuestList(parentQuest.GetQuestList()), parentQuest.CurrQuestId)
		}
	}
	logger.Raw([]byte(data))
	return data
}

// GMReloadConfig 重载配置表(服务器执行热更配置表操作)
//func (g *GMCmd) GMReloadConfig() string {
//	gdconf.ReloadGameDataConfig(db.Conn)
//	gdconf.ReplaceGameDataConfig()
//	LoadConfigData2Shm()
//	return "服务器重载配置表成功"
//}

// GMUpdateConfig 更新配置表(服务器拉取指定git分支的表文件)
func (g *GMCmd) GMUpdateConfig(branch string) string {
	out, err := exec.Command("pwd").CombinedOutput()
	if err != nil {
		logger.Error("pwd error: %v", err)
		return "PWD失败:" + err.Error()
	}
	gitPath := strings.ReplaceAll(string(out), "\n", "") + "/game_data_config"
	err = exec.Command("git", "--git-dir="+gitPath+"/.git", "--work-tree="+gitPath, "checkout", "-B", branch, "origin/"+branch).Run()
	if err != nil {
		logger.Error("git switch error: %v", err)
		return "GIT切换配置表分支失败:" + err.Error()
	}
	err = exec.Command("git", "--git-dir="+gitPath+"/.git", "--work-tree="+gitPath, "pull").Run()
	if err != nil {
		logger.Error("git clone error: %v", err)
		return "GIT拉取配置表失败:" + err.Error()
	}
	game_config.LoadConfigTable(db.Conn)
	logger.Info("update config ok")
	return "GIT更新配置表成功"
}

// GMAutoReloadConfig 一键更表(一键更新当前所在分支的服务器表)
//func (g *GMCmd) GMAutoReloadConfig() string {
//	out, err := exec.Command("pwd").CombinedOutput()
//	if err != nil {
//		logger.Error("pwd error: %v", err)
//		return "PWD失败:" + err.Error()
//	}
//	gitPath := strings.ReplaceAll(string(out), "\n", "") + "/game_data_config"
//	err = exec.Command("git", "--git-dir="+gitPath+"/.git", "--work-tree="+gitPath, "pull").Run()
//	if err != nil {
//		logger.Error("git clone error: %v", err)
//		return "GIT拉取配置表失败:" + err.Error()
//	}
//	gdconf.ReloadGameDataConfig(db.Conn)
//	gdconf.ReplaceGameDataConfig()
//	LoadConfigData2Shm()
//	return "一键更表成功"
//}

// GMGetConfigBranch 获取配置表分支名(获取服务器当前所在配置表的git分支)
func (g *GMCmd) GMGetConfigBranch() string {
	out, err := exec.Command("pwd").CombinedOutput()
	if err != nil {
		logger.Error("pwd error: %v", err)
		return "PWD失败:" + err.Error()
	}
	gitPath := strings.ReplaceAll(string(out), "\n", "") + "/game_data_config"
	out, err = exec.Command("git", "--git-dir="+gitPath+"/.git", "--work-tree="+gitPath, "branch").CombinedOutput()
	if err != nil {
		logger.Error("git branch error: %v", err)
		return "获取配置表分支名失败:" + err.Error()
	}
	for _, s := range strings.Split(string(out), "\n") {
		if strings.Contains(s, "*") {
			return s
		}
	}
	return "获取配置表分支名失败:未找到当前分支"
}

// GMSetRoleFightProp 设置角色战斗属性
func (g *GMCmd) GMSetRoleFightProp(roleId int32, propId int32, propValue int32) bool {
	role := g.User.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, g.User.GetUid())
		return false
	}
	for i := 0; i < len(role.FightPropOverrideList); i++ {
		fightProp := &(role.FightPropOverrideList[i])
		if fightProp.PropId == propId {
			fightProp.PropValue = propValue
			SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: g.User.PacketUserRole(role)}, nil, g.User)
			return true
		}
	}
	for i := 0; i < len(role.FightPropOverrideList); i++ {
		fightProp := &(role.FightPropOverrideList[i])
		if fightProp.PropId == 0 {
			fightProp.PropId = propId
			fightProp.PropValue = propValue
			SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: g.User.PacketUserRole(role)}, nil, g.User)
			return true
		}
	}
	logger.Error("fight prop override list overflow, uid: %v", g.User.GetUid())
	return false
}

// GMResetRoleFightProp 重置角色战斗属性
func (g *GMCmd) GMResetRoleFightProp(roleId int32) bool {
	role := g.User.GetRoleById(roleId)
	if role == nil {
		logger.Error("get role is nil, roleId: %v, uid: %v", roleId, g.User.GetUid())
		return false
	}
	for i := 0; i < len(role.FightPropOverrideList); i++ {
		role.FightPropOverrideList[i].PropId = 0
		role.FightPropOverrideList[i].PropValue = 0
	}
	SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: g.User.PacketUserRole(role)}, nil, g.User)
	return true
}

// GMUseItem 使用道具
func (g *GMCmd) GMUseItem(itemId int32, itemCount int32) bool {
	itemReq := AutoFoundItem(map[int32]int32{itemId: itemCount}, g.User)
	if itemReq == nil {
		logger.Error("auto found item error, itemId: %v, itemCount: %v, uid: %v", itemId, itemCount, g.User.GetUid())
		return false
	}
	UseItem(itemReq, g.User)
	return true
}

// GMClearEquip 清除全部装备
func (g *GMCmd) GMClearEquip() bool {
	for i := 0; i < len(g.User.Equip); i++ {
		equip := &(g.User.Equip[i])
		if equip.Id.NewVal == 0 {
			continue
		}
		if equip.Id.OldVal != 0 {
			equip.Clear()
		} else {
			equip.MemInit()
		}
	}
	for i := 0; i < len(g.User.EquipJewel); i++ {
		jewel := &(g.User.EquipJewel[i])
		if jewel.Id.NewVal == 0 {
			continue
		}
		if jewel.Id.OldVal != 0 {
			jewel.Clear()
		} else {
			jewel.MemInit()
		}
	}
	g.GMKickPlayer()
	return true
}

// GMClearWeapon 清除全部武器
func (g *GMCmd) GMClearWeapon() bool {
	for i := 0; i < len(g.User.UserWeapon.WeaponList); i++ {
		weapon := &(g.User.UserWeapon.WeaponList[i])
		weapon.MemInit()
	}
	g.GMKickPlayer()
	return true
}

// GMAddAllEquip 添加全部装备
func (g *GMCmd) GMAddAllEquip(count int32) bool {
	itemMap := make(map[int32]int32)
	for _, itemConfig := range gdconf.GetItemConfigMap() {
		if itemConfig.Type != gdconf.ITEM_TYPE_EQUIP && itemConfig.Type != gdconf.ITEM_TYPE_EQUIP_JEWEL {
			continue
		}
		itemMap[itemConfig.ItemId] = count
	}
	g.User.FreeNet = true
	ret := AddItems(itemMap, g.User)
	g.User.FreeNet = false
	if ret != config.OK {
		logger.Error("add equip error, ret: %v, uid: %v", ret, g.User.GetUid())
		return false
	}
	g.GMKickPlayer()
	return true
}

// GMAddAllWeapon 添加全部武器
func (g *GMCmd) GMAddAllWeapon(count int32) bool {
	itemMap := make(map[int32]int32)
	for _, itemConfig := range gdconf.GetItemConfigMap() {
		if itemConfig.Type != gdconf.ITEM_TYPE_WEAPON {
			continue
		}
		itemMap[itemConfig.ItemId] = count
	}
	g.User.FreeNet = true
	ret := AddItems(itemMap, g.User)
	g.User.FreeNet = false
	if ret != config.OK {
		logger.Error("add weapon error, ret: %v, uid: %v", ret, g.User.GetUid())
		return false
	}
	g.GMKickPlayer()
	return true
}

// GMDumpEquip 转储装备数据
func (g *GMCmd) GMDumpEquip() string {
	data := ""
	data += fmt.Sprintf("============================== GMDumpEquip uid: %v ==============================\n", g.User.GetUid())
	for _, equip := range g.User.GetEquipMap() {
		equipData, _ := json.Marshal(equip)
		data += fmt.Sprintf("[Equip] data: %v\n", string(equipData))
	}
	for _, equipJewel := range g.User.GetEquipJewelMap() {
		equipJewelData, _ := json.Marshal(equipJewel)
		data += fmt.Sprintf("[EquipJewel] data: %v\n", string(equipJewelData))
	}
	logger.Raw([]byte(data))
	return data
}

// GMReloadServerConfig 更新服务器配置文件
func (g *GMCmd) GMReloadServerConfig() bool {
	game_config.InitConfig()
	logger.ReloadLoggerConfig(game_config.GetConfig().LogLevel)
	return true
}

// GMTriggerUnlockFight 触发解锁战斗
func (g *GMCmd) GMTriggerUnlockFight(cond int32, paramList string) bool {
	param := make([]int32, 0)
	if paramList != "" {
		for _, s := range strings.Split(paramList, "#") {
			p, err := strconv.Atoi(s)
			if err != nil {
				logger.Error("param format error, paramList: %v, uid: %v", paramList, g.User.GetUid())
				return false
			}
			param = append(param, int32(p))
		}
	}
	TriggerUnlockMonster(g.User, cond, param...)
	return true
}

// GMDumpScene 转储场景数据
func (g *GMCmd) GMDumpScene() string {
	data := ""
	data += fmt.Sprintf("============================== GMDumpScene uid: %v ==============================\n", g.User.GetUid())
	for _, scene := range g.User.GetSceneMap() {
		monsterData, _ := json.Marshal(g.User.GetSceneMonsterMap(scene.SceneId))
		getGadgetData, _ := json.Marshal(g.User.GetSceneGadgetMap(scene.SceneId))
		data += fmt.Sprintf("[Scene] Id: %v, Tag: %v, Monster: %v, Gadget: %v\n",
			scene.SceneId, scene.SceneTag, string(monsterData), string(getGadgetData))
	}
	logger.Raw([]byte(data))
	return data
}

// GMServerTimeOffset 服务器时间偏移
func (g *GMCmd) GMServerTimeOffset(offset int64) bool {
	if offset < -86400*365*50 || offset > 86400*365*50 {
		logger.Error("time offset too big, offset: %v", offset)
		return false
	}
	sharemem.MyShm.TimeOffset = offset
	logger.Info("set server time offset: %v", offset)
	return true
}

// GMSendMail 发送邮件
func (g *GMCmd) GMSendMail(title string, content string, sender string, expireTime uint32, isImportance bool, itemParam string) {
	itemMap := make(map[int32]int32)
	if itemParam != "" {
		for _, itemStr := range strings.Split(itemParam, "|") {
			split := strings.Split(itemStr, "#")
			if len(split) != 2 {
				logger.Error("send mail item param format error, itemParam: %v", itemParam)
				return
			}
			itemId, err := strconv.Atoi(split[0])
			if err != nil {
				logger.Error("send mail item param format error, itemParam: %v, err: %v", itemParam, err)
				return
			}
			count, err := strconv.Atoi(split[1])
			if err != nil {
				logger.Error("send mail item param format error, itemParam: %v, err: %v", itemParam, err)
				return
			}
			itemMap[int32(itemId)] += int32(count)
		}
	}
	AddUserMail(title, content, sender, expireTime, isImportance, itemMap, g.User)
}

// GMDumpPlayerData 转储玩家数据
func (g *GMCmd) GMDumpPlayerData() {
	DumpPlayerData(g.User)
}

// GMTest 测试
func (g *GMCmd) GMTest(id int32) {
}

// GMUnlockAllHomeBuilding 解锁全部家园建筑
func (g *GMCmd) GMUnlockAllHomeBuilding() bool {
	for buildingId := range gdconf.GetHomeBuildingConfigMap() {
		g.User.AddUnlockBuilding(buildingId)
	}
	return true
}

// GMSetActivityPoint 设置活动活跃度
func (g *GMCmd) GMSetActivityPoint(daily uint32, weekly uint32) {
	g.User.UserActivity.DailyTaskPoint = daily
	g.User.UserActivity.WeeklyTaskPoint = weekly
	g.User.TriggerActivityTask(gdconf.ActivityTaskFinishCondDailyTaskPoint)
	g.GMKickPlayer()
}

// GMSetCurrCollCount 设置当前剩余冲撞次数
func (g *GMCmd) GMSetCurrCollCount(collCount int32) {
	g.User.UserScene.CurrCollCount = collCount
	SendMsg(config.SC_SceneDashUpdateNtf, &pb.SC_SceneDashUpdateNtf{CurrCollCount: int64(g.User.UserScene.CurrCollCount)}, nil, g.User)
}

func (g *GMCmd) GMSwitchSceneTag() {
	var pScene = g.User.GetSceneById(g.User.SceneId)
	if pScene.SceneTag == 0 {
		pScene.SceneTag = 1
	} else {
		pScene.SceneTag = 0
	}
	//UserSceneDataNotify(g.User, g.User.SceneId, g.User.SceneId)
}

func (g *GMCmd) GMOpenFunc(Id int32) {
	var newList = make([]int32, 0)
	if Id != 0 {
		if gdconf.GetOpenStateConfig(Id) != nil {
			if !g.User.UserQuest.CheckOpenState(Id) {
				g.User.UserQuest.UnlockOpenState(Id)
				newList = append(newList, Id)
			}
		}
	} else {
		for _, openStateConfig := range gdconf.GetOpenStateConfigMap() {
			if g.User.UserQuest.CheckOpenState(openStateConfig.OpenStateId) {
				continue
			}
			g.User.UserQuest.UnlockOpenState(openStateConfig.OpenStateId)
			newList = append(newList, openStateConfig.OpenStateId)
		}
	}
	SendMsg(config.SC_OpenFuncNtf, &pb.SC_OpenFuncNtf{FuncIdList: g.User.UserQuest.GetOpenState(), NewFuncIdList: newList}, nil, g.User)
}

func (g *GMCmd) GMChangeGadgetState(sceneId, GadgetId, stage int32) {
	var pScene = g.User.GetSceneById(sceneId)
	if pScene == nil {
		return
	}
	var pGadget = g.User.GetSceneGadgetById(sceneId, GadgetId)
	if pGadget == nil {
		pGadget.GadgetState = int8(stage)
	}
	UserSceneGadgetNotify(g.User, pScene, pGadget)
}

func (g *GMCmd) GMUnlockCodeX() {
	for _, codex := range gdconf.GetCodexConfigMap() {
		g.User.AddCodex(codex.CodexId)
	}
	g.GMKickPlayer()
}

/**************************************** GM功能函数 ****************************************/

func (g *GMCmd) ServerPanicTest() {
	panic("ServerPanicTest")
}

func (g *GMCmd) ReflectGetUserData(exp string) any {
	ok, currRefValue := ParseReflectDataExp(exp, g.User)
	if !ok {
		logger.Error("parse reflect data exp error, exp: %v", exp)
		return nil
	}
	logger.Info("reflect get user data, exp: %v, value: %v, uid: %v", exp, currRefValue.Interface(), g.User.GetUid())
	return currRefValue.Interface()
}

func (g *GMCmd) ReflectSetUserData(exp string, value string) bool {
	ok, currRefValue := ParseReflectDataExp(exp, g.User)
	if !ok {
		logger.Error("parse reflect data exp error, exp: %v", exp)
		return false
	}
	ok, newRefValue := ParseStringToRefValue(currRefValue.Kind(), value)
	if !ok {
		logger.Error("parse string to ref value error, value: %v", value)
		return false
	}
	currRefValue.Set(newRefValue)
	logger.Info("reflect set user data, exp: %v, value: %v, uid: %v", exp, currRefValue.Interface(), g.User.GetUid())
	return true
}

func (g *GMCmd) GetOnlineUidList() []int64 {
	onlineUidList := make([]int64, 0)
	for _, user := range sharemem.GetUserMap() {
		if user.Shm_user.IsOnline {
			onlineUidList = append(onlineUidList, user.Shm_user.GetUid())
		}
	}
	logger.Info("get online uid list: %v", onlineUidList)
	return onlineUidList
}

func (g *GMCmd) SaveUserAllData() {
	g.User.SetSync()
	for i := 0; i < len(g.User.Item.Normal); i++ {
		g.User.Item.Normal[i].SetSync()
	}
	for i := 0; i < len(g.User.Item.Special); i++ {
		g.User.Item.Special[i].SetSync()
	}
	for i := 0; i < len(g.User.Role); i++ {
		g.User.Role[i].SetSync()
	}
	for i := 0; i < len(g.User.Equip); i++ {
		g.User.Equip[i].SetSync()
	}
	for i := 0; i < len(g.User.EquipJewel); i++ {
		g.User.EquipJewel[i].SetSync()
	}
	for i := 0; i < len(g.User.Team); i++ {
		g.User.Team[i].SetSync()
	}
	for i := 0; i < len(g.User.Mail); i++ {
		g.User.Mail[i].SetSync()
	}
	res := MD_User(g.User.Index, true)
	if res != nil {
		logger.Error("save user fail,error :%v, uid: %v", res, g.User.GetUid())
	}
}

type GMCmd struct {
	User *sharemem.User
}

var (
	GMCmdInst     = new(GMCmd)
	GMCmdRefValue = reflect.ValueOf(GMCmdInst)
)

func GmReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_GmReq, new(pb.CS_GmReq), buf, user).(*pb.CS_GmReq)
	if !ok {
		return config.PROTO_ERROR
	}

	if !game_config.GetConfig().DevEnv && !user.IsGmUser {
		return SendMsg(config.SC_GmRsp, &pb.SC_GmRsp{RetCode: config.OK, Ok: false, Msg: "没有权限"}, buf, user)
	}

	GMCmdInst.User = user

	commandText := req.GmCmd
	commandText = strings.ReplaceAll(commandText, "\r\n", "\n")
	for _, commandLine := range strings.Split(commandText, "\n") {
		commandLine = strings.ReplaceAll(commandLine, " ", "")
		if commandLine == "" {
			continue
		}
		beginIndex := strings.Index(commandLine, "(")
		endIndex := strings.Index(commandLine, ")")
		if beginIndex == 0 || beginIndex == -1 || endIndex == -1 || beginIndex >= endIndex {
			SendMsg(config.SC_GmRsp, &pb.SC_GmRsp{RetCode: config.OK, Ok: false, Msg: "GM命令格式解析失败"}, nil, user)
			continue
		}
		logger.Info("run gm cmd: %v", commandLine)
		funcName := commandLine[:beginIndex]
		funcParam := commandLine[beginIndex+1 : endIndex]
		var paramList []string = nil
		if funcParam == "" {
			paramList = make([]string, 0)
		} else {
			paramList = strings.Split(funcParam, ",")
		}
		if len(funcName) < 2 || funcName[0:2] != "GM" {
			SendMsg(config.SC_GmRsp, &pb.SC_GmRsp{RetCode: config.OK, Ok: false, Msg: "客户端无权执行内部命令"}, nil, user)
			continue
		}
		ok, msg := CallGMCmd(funcName, paramList)

		SendMsg(config.SC_GmRsp, &pb.SC_GmRsp{RetCode: config.OK, Ok: ok, Msg: msg}, nil, user)
	}

	GMCmdInst.User = nil

	return config.OK
}

func CallGMCmdP(funcName string, paramList []string) (ok bool, msg string) {
	defer func() {
		if err := recover(); err != nil {
			logger.Error("!!! CALL GM CMD PANIC !!!")
			logger.Error("error: %v", err)
			logger.Error("stack: %v", logger.Stack())
			ok = false
			msg = "call gm cmd panic"
			return
		}
	}()
	return CallGMCmd(funcName, paramList)
}

func CallGMCmd(funcName string, paramList []string) (bool, string) {
	fn := GMCmdRefValue.MethodByName(funcName)
	if !fn.IsValid() {
		logger.Error("gm func not valid, func: %v", funcName)
		return false, "GM函数名不存在"
	}
	if fn.Type().NumIn() != len(paramList) {
		logger.Error("gm func param num not match, func: %v, need: %v, give: %v", funcName, fn.Type().NumIn(), len(paramList))
		return false, "GM函数参数数量不匹配"
	}
	in := make([]reflect.Value, fn.Type().NumIn())
	for i := 0; i < fn.Type().NumIn(); i++ {
		kind := fn.Type().In(i).Kind()
		param := paramList[i]
		ok, value := ParseStringToRefValue(kind, param)
		if !ok {
			return false, "GM函数参数类型不支持"
		}
		in[i] = value
	}
	out := fn.Call(in)
	ret := make([]any, 0)
	for _, v := range out {
		ret = append(ret, v.Interface())
	}
	data, _ := json.Marshal(ret)
	return true, string(data)
}

func ParseStringToRefValue(kind reflect.Kind, param string) (bool, reflect.Value) {
	switch kind {
	case reflect.Int:
		val, err := strconv.ParseInt(param, 10, 64)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(int(val))
	case reflect.Uint:
		val, err := strconv.ParseUint(param, 10, 64)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(uint(val))
	case reflect.Int8:
		val, err := strconv.ParseInt(param, 10, 8)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(int8(val))
	case reflect.Uint8:
		val, err := strconv.ParseUint(param, 10, 8)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(uint8(val))
	case reflect.Int16:
		val, err := strconv.ParseInt(param, 10, 16)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(int16(val))
	case reflect.Uint16:
		val, err := strconv.ParseUint(param, 10, 16)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(uint16(val))
	case reflect.Int32:
		val, err := strconv.ParseInt(param, 10, 32)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(int32(val))
	case reflect.Uint32:
		val, err := strconv.ParseUint(param, 10, 32)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(uint32(val))
	case reflect.Int64:
		val, err := strconv.ParseInt(param, 10, 64)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(val)
	case reflect.Uint64:
		val, err := strconv.ParseUint(param, 10, 64)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(val)
	case reflect.Float32:
		val, err := strconv.ParseFloat(param, 32)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(float32(val))
	case reflect.Float64:
		val, err := strconv.ParseFloat(param, 64)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(val)
	case reflect.Bool:
		val, err := strconv.ParseBool(param)
		if err != nil {
			return false, reflect.Value{}
		}
		return true, reflect.ValueOf(val)
	case reflect.String:
		return true, reflect.ValueOf(param)
	default:
		return false, reflect.Value{}
	}
}

func ReflectElemPtrLoop(value reflect.Value) reflect.Value {
	for i := 0; i < 1000; i++ {
		if value.Kind() != reflect.Ptr {
			return value
		}
		value = value.Elem()
	}
	logger.Error("reflect elem ptr loop times limit")
	return reflect.Value{}
}

func ParseReflectDataExp(exp string, obj any) (ok bool, value reflect.Value) {
	if !strings.Contains(exp, "(Object)") {
		return false, reflect.ValueOf(obj)
	}
	for index, token := range strings.Split(exp, ".") {
		if index == 0 {
			if token != "(Object)" {
				logger.Error("exp format error, exp: %v", exp)
				return false, reflect.Value{}
			}
			value = reflect.ValueOf(obj)
			value = ReflectElemPtrLoop(value)
			continue
		}
		if strings.Contains(token, "[") && strings.Contains(token, "]") {
			beginIndex := strings.Index(token, "[")
			endIndex := strings.Index(token, "]")
			if beginIndex == 0 || beginIndex == -1 || endIndex == -1 || beginIndex >= endIndex {
				logger.Error("exp format error, exp: %v", exp)
				return false, reflect.Value{}
			}
			arrayName := token[0:beginIndex]
			arrayIndex, err := strconv.Atoi(token[beginIndex+1 : endIndex])
			if err != nil {
				logger.Error("exp format error: %v, exp: %v", err, exp)
				return false, reflect.Value{}
			}
			value = value.FieldByName(arrayName)
			value = ReflectElemPtrLoop(value)
			value = value.Index(arrayIndex)
			value = ReflectElemPtrLoop(value)
		} else {
			fieldName := token
			value = value.FieldByName(fieldName)
			value = ReflectElemPtrLoop(value)
		}
	}
	return true, reflect.NewAt(value.Type(), unsafe.Pointer(value.UnsafeAddr())).Elem()
}
